#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
@File   : macro_factor.py
@Time   : 2024/07/25 17:09
@Author : Liuli
@Desc   : None
"""
import numpy as np
import pandas as pd
from sklearn.decomposition import PCA


def get_macrofactor(index, start, end):
    """ 将大类资产数据通过主成分分析获取宏观因子"""
    start = pd.to_datetime(start).strftime('%Y%m%d')
    start_b = (pd.to_datetime(start) - pd.to_timedelta(300, 'days')).strftime('%Y%m%d')
    end = pd.to_datetime(end).strftime('%Y%m%d')

    # data = get_close(index, start, end)
    from WindPy import w
    w.start()
    data = w.wsd(index, "close", start, end, "")
    data = pd.DataFrame(np.array(data.Data).T, index=data.Times, columns=data.Codes)
    data = data.pct_change().dropna(how='all', axis=0)
    data = data.apply(lambda x: (x - x.mean()) / x.std(), axis=0)

    pca = PCA(n_components='mle')
    pca.fit(data)
    factor = pca.fit_transform(data)  # 降维后的数据
    pca_score = pca.explained_variance_ratio_  # 主成分的方差贡献率
    V = pca.components_  # 具有最大方差的成分


def get_hidden_factor(start, end):
    """ 从Wind API 提取数据构建隐含因子"""
    start = pd.to_datetime(start).strftime('%Y%m%d')
    start_b = (pd.to_datetime(start) - pd.to_timedelta(600, 'days')).strftime('%Y%m%d')
    end = pd.to_datetime(end).strftime('%Y%m%d')

    from WindPy import w
    w.start()

    # index = {'H00300.CSI': '沪深300指数', 'HSI.HI': '恒生指数', 'S2707426': '70大中城市二手住宅销售价格指数环比',
    #          'NH0100.NHF': '南华商品指数', 'CBA06501.CS': '中债-7-10年国债财富(总值)指数', 'B.IPE': 'ICE布伦特原油',
    #          'RB.SHF': '螺纹钢', 'S5065106': '猪肉平均批发价', 'CBA04031.CS': '中债-企业债AA财富(3-5年)指数',
    #          'CBA04601.CS': '中债-3-5年期国债财富(总值)指数', 'M0049385': '市盈率:申万大盘指数',
    #          'M0049387': '市盈率:申万小盘指数','USDX.FX': '美元指数', 'VIX.GI': 'CBOE波动率',
    #          'SP500TR.SPI': '标普500指数', '128456.MI': 'MSCI US REIT INDEX', 'S0031510': 'CRB工业原料指数',
    #          'G0005428': '美国10年期通胀国债指数', 'G0000891': '美国10年期国债指数'}
    # data = w.wsd(list(index.keys()), "close", start_b, end, "")
    # data = pd.DataFrame(np.array(data.Data).T, index=data.Times, columns=data.Codes)

    data = pd.read_excel('./data.xlsx', index_col=0)

    # 地产价格月度数据填补到交易日
    for i in data[pd.notna(data['S2707426'])].index:
        seq = list(data.index).index(i)
        for j in range(seq, 0, -1):
            # 向上填补一个交易日数值
            if pd.notna(data.iloc[j]['H00300.CSI']):
                data.loc[data.index[j], 'S2707426'] = data.loc[i, 'S2707426']
                break

    data = data[pd.notna(data['H00300.CSI'])].copy()
    data[['S2707426', 'G0005428', 'G0000891']] = data[['S2707426', 'G0005428', 'G0000891']] / 100
    cols = list(data.columns)
    cols.remove('S2707426')
    data[cols] = data[cols].ffill(axis=0, limit=5)

    # 经济增长风险因子
    vol_c = data[['H00300.CSI', 'HSI.HI', 'NH0100.NHF']].pct_change().apply(lambda x: x.rolling(252).std()*np.sqrt(252))
    vol_c2 = data['S2707426'].dropna()
    vol_c2 = vol_c2.rolling(12).std() * np.sqrt(12)
    vol_c = pd.merge(vol_c, vol_c2, left_index=True, right_index=True, how='left')
    vol_c.ffill(axis=0, inplace=True)
    vol_c = 1 / vol_c
    vol_c = vol_c.apply(lambda x: x/x.sum(skipna=False), axis=1)
    # vol_c.dropna(how='any', inplace=True)
    # data['S2707426'] = (data['S2707426'].dropna() + 1).cumprod().pct_change(12).reindex(data.index, method='ffill')
    data['S2707426'] = (data['S2707426'].dropna() + 1).cumprod().reindex(data.index, method='ffill')
    data['growth'] = (data[['H00300.CSI', 'HSI.HI', 'NH0100.NHF', 'S2707426']].pct_change()*vol_c).sum(skipna=False, axis=1)
    # data['growth'] = (data['growth']+1).cumprod()

    # 通胀风险因子
    data[['B.IPE', 'RB.SHF', 'S5065106']] = data[['B.IPE', 'RB.SHF', 'S5065106']].pct_change()
    data['inflation'] = data[['B.IPE', 'RB.SHF', 'S5065106']].mean(axis=1)

    # 信用风险因子
    data['credit'] = data['CBA04031.CS'].pct_change() - data['CBA04601.CS'].pct_change()

    # 期限利差因子
    data['term'] = data['CBA06501.CS'].pct_change() - data['CBA04601.CS'].pct_change()

    # 流动性风险因子
    data['liquidity'] = data['M0049387'] / data['M0049385']
    data['liquidity'] = data['liquidity'].ffill()
    data['liquidity'] = data['liquidity'].pct_change()

    # 海外经济增长风险因子
    vol_o = data[['SP500TR.SPI', '128456.MI', 'S0031510']].pct_change().apply(lambda x: x.rolling(252).std()*np.sqrt(252))
    vol_o = 1 / vol_o
    vol_o = vol_o.apply(lambda x: x/x.sum(skipna=False), axis=1)
    data['growth_us'] = (data[['SP500TR.SPI', '128456.MI', 'S0031510']].pct_change()*vol_o).sum(skipna=False, axis=1)

    # 海外通胀风险因子
    data['inflation_us'] = (data['G0000891'] - data['G0005428']).pct_change()

    # 利率、汇率、流动性风险因子
    data.rename(columns={'CBA06501.CS': 'interest_rate', 'USDX.FX': 'exchange_rate', 'VIX.GI': 'liquidity_us'}, inplace=True)
    data['interest_rate'] = data['interest_rate'].pct_change()
    data['exchange_rate'] = data['exchange_rate'].pct_change()

    data = data.loc[start: end, ['growth', 'interest_rate', 'inflation', 'credit', 'term', 'liquidity', 'exchange_rate',
                                 'growth_us', 'inflation_us']].copy()
    return data


if __name__ == "__main__":
    start = '2008-01-01'
    end = '2024-10-31'
    # 备选：中债信用债财富('CBA02701.CS'), 中债-国开行债券总财富(7-10年)指数(CBA02551.CS), ICE布油(B.IPE)
    # 300收益, 500收益, 中证1000全收益, 中债-7-10年国债财富(总值)指数, 中债-3-5年期国债财富(总值)指数, 中债-0-1年国债财富(总值)指数,
    # 中债-优选投资级信用债指数, 标普500, SHFE黄金, SHFE铜, INE原油, 货币基金
    index = ['H00300.CSI', 'H00905.CSI', 'H00852.SH', 'CBA06501.CS', 'CBA04601.CS', 'CBA14101.CS', 'CBA20901.CS',
             'SP500TR.SPI', 'AU.SHF', 'CU.SHF', 'SC.INE', 'H11025.CSI']

    data = get_hidden_factor(start, end)

    import statsmodels.api as sm
    cycle, trend = sm.tsa.filters.hpfilter(data, lamb=129600)
